/**
 * 
 */

package us.gaaoc.framework.util.pdf;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

import us.gaaoc.framework.model.DocPageRange;
import us.gaaoc.framework.util.collections.FastGrowableIntArray;

/**
 * Class to update page ranges of document if text based targets are found
 * indicating page splits to override page ranges from the database.
 * 
 * 
 * Logic for conversion:
 * Example Pattern - * # * # * # * # * # *
 * *'s = 6
 * #'s =  5
 * 
 * Always will be one less # sign than *'s.
 * When converting, first page won't change and end page won't change. Assumes
 * that the documents of interest start on the first page and that document 
 * splitting occurs between contiguous documents.
 *
 * @author mcelratr
 * 
 */
public class PageRangesFromTextTargetsUtility {

	public List<DocPageRange> pageRangesFromTargetsCheck(
			InputStream fisPassedIn,
			List<DocPageRange> dprListToCheckPassedIn) {
		List<DocPageRange> dprListToCheck = dprListToCheckPassedIn;
		List<DocPageRange> dprListUpdated = new ArrayList<DocPageRange>();
		// TODO Rework DataModel to be able to pull the target from db 
		//String splitTarget = "XX SPLIT HERE XX";
		int pagesWhereSplitTargetFound[];
		int pageWhereEndTargetFound;

		try {
			PDFTextTargetsUtility pdfTTU = new PDFTextTargetsUtility();
			/*
			 * TODO Refactor PDFTextTargetsUtility to create method which only
			 * returns the int array of pages where target found.
			 */
			pagesWhereSplitTargetFound = pdfTTU.getPagesWhereTargetIsFound();
			pageWhereEndTargetFound = pdfTTU.getLastPageOfDocument();
			if (pagesWhereSplitTargetFound.length > 0) {
				dprListUpdated = modifyPageRangesBasedOnTextTargets(dprListToCheck,
						pagesWhereSplitTargetFound, pageWhereEndTargetFound);
			} else {
				// If no targets found, then send back unmodified page ranges
				dprListUpdated = dprListToCheck;
			}
		} catch (Exception ex) {
			ex.printStackTrace();
			dprListUpdated = dprListToCheck;
		}

		return dprListUpdated;
	}
	
	/*
	public List<DocPageRange> pageRangesFromTargetsCheck(
			FileInputStream fisPassedIn,
			List<DocPageRange> dprListToCheckPassedIn) {
		FileInputStream fis = fisPassedIn;
		List<DocPageRange> dprListToCheck = dprListToCheckPassedIn;
		List<DocPageRange> dprListUpdated = new ArrayList<DocPageRange>();
		// TODO Rework DataModel to be able to pull the target from db 
		//String splitTarget = "XX SPLIT HERE XX";
		String splitTarget = "SPLITDOCUMENT";
		int pagesWhereSplitTargetFound[];
		int pageWhereEndTargetFound;

		try {
			PDFTextTargetsUtility pdfTTU = new PDFTextTargetsUtility();
			
			 * TODO Refactor PDFTextTargetsUtility to create method which only
			 * returns the int array of pages where target found.
			 
			float sigCoordinates[] = pdfTTU.findTextTargetCoordinates(splitTarget,
					fis, false, false);
			pagesWhereSplitTargetFound = pdfTTU.getPagesWhereTargetIsFound();
			pageWhereEndTargetFound = pdfTTU.getLastPageOfDocument();
			if (pagesWhereSplitTargetFound.length > 0) {
				dprListUpdated = modifyPageRangesBasedOnTextTargets(dprListToCheck,
						pagesWhereSplitTargetFound, pageWhereEndTargetFound);
			} else {
				// If no targets found, then send back unmodified page ranges
				dprListUpdated = dprListToCheck;
			}
		} catch (Exception ex) {
			ex.printStackTrace();
			dprListUpdated = dprListToCheck;
		}

		return dprListUpdated;
	}*/


	private List<DocPageRange> modifyPageRangesBasedOnTextTargets(
			List<DocPageRange> dprListToUpdatePassedIn,
			int[] pagesWhereTargetFoundPassedIn,
			int pageWhereEndTargetFoundPassedIn) {
		List<DocPageRange> dprListToUpdate = dprListToUpdatePassedIn;
		List<DocPageRange> dprListUpdated = new ArrayList<DocPageRange>();
		int[] pagesWhereTargetFound = pagesWhereTargetFoundPassedIn;
		FastGrowableIntArray pageRangeStartsTemp = new FastGrowableIntArray();
		FastGrowableIntArray pageRangeEndsTemp = new FastGrowableIntArray();
		int endPage = pageWhereEndTargetFoundPassedIn;  
		int pageRangeStarts[];
		int pageRangeStartsFromTargets[];
		int pageRangeEndsFromTargets[];
		/*
		 * Update document page range list with updated page ranges based on
		 * targets for page splitting found in the PDF document.
		 */
		/*
		 * 1. Extract out page ranges into arrays
		 */
		DocPageRange dpr;
		int dprListSize = dprListToUpdate.size();
		for (int i = 0; i < dprListSize; i++) {
			dpr = dprListToUpdate.get(i);
			pageRangeStartsTemp.add(dpr.getPageRangeStart());
			pageRangeEndsTemp.add(dpr.getPageRangeEnd());
		}
		pageRangeStarts = pageRangeStartsTemp.toArray();
		/*
		 * 2. Update end page of page range before and start page of page range
		 * after where the targets where found in the PDF
		 */
		// Validate that page splits found matches the amount of page splits
		// expected
		int numberOfTargetPagesFound = pagesWhereTargetFound.length;
		int numberOfPageRangeStarts = pageRangeStarts.length;
		// Remember to add one since the number of splits will always be one
		// less than the number of pages
		if ((numberOfTargetPagesFound + 1) == numberOfPageRangeStarts) {
			// Convert array of page split target page numbers into start
			// and end numbers for page ranges.
			pageRangeStartsFromTargets = incrementPageRange(pagesWhereTargetFound, 1);
			pageRangeEndsFromTargets = incrementPageRange(pagesWhereTargetFound, -1);
			// Update page ranges in list
			for (int i = 0; i < dprListSize; i++) {
				dpr = dprListToUpdate.get(i);
				// For all but the last loop . . 
				if (i < (dprListSize - 1)) {
					//dpr2 = dprListToUpdate.get(i + 1);
					// Update the start page of the next page range in the list
					//dpr2.setPageRangeStart(pageRangeStartsFromTargets[i]);
					if (i >= 1) {  // Skip the first one since it will automatically start at 1
						//dpr.setPageRangeStart(pageRangeStartsFromTargets[i - 1]);
					}
					if (i == 0) {
						// If this is the first loop, set first page to start of
						// document.
						//dpr.setPageRangeStart(1);
					}
					// Update the current page range end page
					//dpr.setPageRangeEnd(pageRangeEndsFromTargets[i]);
					//dprListToUpdate.set(i + 1, dpr2);
					dprListToUpdate.set(i, dpr);
				} else if (i == (dprListSize - 1)) {
					// Update the page range start
					//dpr.setPageRangeStart(pageRangeStartsFromTargets[i - 1]);
					// On the last loop, only set the end page
					//dpr.setPageRangeEnd(endPage);
				}
				dprListToUpdate.set(i, dpr);
				
			}
			dprListUpdated = dprListToUpdate;
		} else {
			// If the page splits don't match the number of page splits expected
			// don't convert, simply pass back original page split ranges.
			dprListUpdated = dprListToUpdate;
		}
		/*
		 * 3. Write back the updated page ranges to the Document Page Range List
		 */
		return dprListUpdated;
	}

	private int[] incrementPageRange(int[] pageNumbersToConvertPassedIn, int incrementPassedIn) {
		int[] pageNumbersToConvert = pageNumbersToConvertPassedIn;
		int arrayLength = pageNumbersToConvert.length;
		int[] convertedPageNumbers = new int[arrayLength];
		int increment = incrementPassedIn;
		
		for (int i = 0; i < arrayLength; i++) {
			convertedPageNumbers[i] = (pageNumbersToConvert[i] + increment);
		}
		return convertedPageNumbers;
	}

}
